package org.example.service;

import com.alipay.remoting.exception.CodecException;
import io.vertx.core.Handler;
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.net.NetServer;
import io.vertx.core.net.NetSocket;
import io.vertx.core.parsetools.RecordParser;
import lombok.extern.slf4j.Slf4j;
import org.example.CommonMsg;
import org.example.command.OrderCmd;
import org.example.conter.CounterPacket;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;

@Service
@Slf4j
public class CounterServer {
    @Value("${server4.counter.port}")
    private int counterServerPort;
    @Autowired
    OrderCmdCache cache;
    private Vertx vertx = Vertx.vertx();

    /**
     * Gateway启动TCP服务，等待柜台(counter)发送委托信息
     */
    @PostConstruct
    private void init() {
        NetServer server = vertx.createNetServer();
        server.connectHandler(new CounterContentHandler(cache));
        server.listen(counterServerPort, res -> {
           if(res.succeeded()) {
              log.info("gateway startup success at port:{}", counterServerPort);
           }else {
               log.error("gateway startup fail");
           }
        });
    }


}

class CounterContentHandler implements Handler<NetSocket> {

    private final OrderCmdCache cache;

    public CounterContentHandler(OrderCmdCache cache) {
        this.cache = cache;
    }

    @Override
    public void handle(NetSocket netSocket) {
        //粘包现象。
        final RecordParser parser = RecordParser.newFixed(CounterPacket.HEADER_LENGTH);
        parser.setOutput(new ContentHandler(parser, cache));
        netSocket.handler(parser);
        netSocket.closeHandler(close -> {
            System.out.println("连接关闭中。。。。。。");
        });
        netSocket.exceptionHandler(ex -> {
            System.out.println("连接异常。。。。");
            ex.printStackTrace();
        });
    }
}
@Slf4j
class ContentHandler implements Handler<Buffer> {

    private final RecordParser parser;
    private final OrderCmdCache cache;
    boolean hasReadHeader = false;
    CommonMsg msg = null;

    public ContentHandler(RecordParser parser, OrderCmdCache cache) {
        this.parser = parser;
        this.cache = cache;
    }

    @Override
    public void handle(Buffer buffer) {
        System.out.println("-------------------get msg");
        if(!hasReadHeader) {
            msg = CounterPacket.readCommonMsg(buffer);
            parser.fixedSizeMode(msg.getBodyLength());
            hasReadHeader = true;
            System.out.println("init....." + msg.toString());
        }else {
            System.out.println("------------will read body.");
            byte[] bodyBytes = buffer.getBytes();
            if(!msg.check(bodyBytes)) {
                log.error("illegal byte body exist from client:");
                return;
            }else {
                msg.setBody(bodyBytes);
                msg.setTimestamp(System.currentTimeMillis());
                try {
                    OrderCmd orderCmd = OrderCmd.deserialize(bodyBytes);// msg.deserialize(OrderCmd.class);
                    System.out.println("msg = " + orderCmd.toString());
                    cache.cache(orderCmd);
                } catch (CodecException e) {
                    log.error("deserializer failure ");
                }
                this.hasReadHeader = false;
                parser.fixedSizeMode(CounterPacket.HEADER_LENGTH);
            }
        }
    }

}
